/*
 * @(#) $Header$
 *
 * Copyright (C) 2007  Forklabs Daniel Léonard
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package ca.forklabs.media.jai;

import java.awt.image.renderable.ParameterBlock;
import java.util.Collection;
import javax.media.jai.EnumeratedParameter;
import javax.media.jai.OperationDescriptor;
import javax.media.jai.OperationDescriptorImpl;
import javax.media.jai.ParameterListDescriptor;
import javax.media.jai.util.Range;
import ca.forklabs.media.jai.DescriptorUtil;

/**
 * Class {@code CollectionDescriptor} helps in creating
 * {@link OperationDescriptor} that have collections has input source.
 *
 * @author   <a href="mailto:forklabs at gmail.com?subject=ca.forklabs.media.jai.CollectionDescriptor">Daniel Léonard</a>
 * @version $Revision$
 */
@SuppressWarnings("serial")
public abstract class CollectionDescriptor extends OperationDescriptorImpl {

//---------------------------
// Inner classes
//---------------------------

   /**
    * Empty implementation of interface {@link ParameterListDescriptor}.
    */
   protected static class EmptyParameterListDescriptor implements ParameterListDescriptor {

      /**
       * Constructor.
       */
      public EmptyParameterListDescriptor() {
      // nothing
         }

      /**
       * The default is to have no parameters.
       * @return   always <em>0</em>.
       */
      @Override
      public int getNumParameters() {
         int num_parameters = 0;
         return num_parameters;
         }

      /**
       * The default is to have no parameters.
       * @return   always {@code null}.
       */
      @Override
      public Class<?>[] getParamClasses() {
         Class<?>[] clazzes = null;
         return clazzes;
         }

      /**
       * The default is to have no parameters.
       * @return   never.
       * @exception   IllegalArgumentException   always.
       */
      @Override
      public Object getParamDefaultValue(String name) {
         String message = CollectionDescriptor.getUnknownParameterErrorMessage(name);
         throw new IllegalArgumentException(message);
         }

      /**
       * The default is to have no parameters.
       * @return   always {@code null}.
       */
      @Override
      public Object[] getParamDefaults() {
         Object[] defaults = null;
         return defaults;
         }

      /**
       * The default is to have no parameters.
       * @return   always {@code null}.
       */
      @Override
      public String[] getParamNames() {
         String[] names = null;
         return names;
         }

      /**
       * There are no enumerator parameters.
       * @return   always {@code null}.
       */
      @Override
      public String[] getEnumeratedParameterNames() {
      // no enumerated parameters
         String[] names = null;
         return names;
         }

      /**
       * There are no enumerator parameters.
       * @return   never.
       * @exception   UnsupportedOperationException   always.
       */
      @Override
      public EnumeratedParameter[] getEnumeratedParameterValues(String name) {
      // no enumerated parameters
         String message = CollectionDescriptor.getNoEnumeratedParametersErrorMessage();
         throw new UnsupportedOperationException(message);
         }

      /**
       * There are no range parameters.
       * @return   alway {@code null}.
       */
      @Override
      public Range getParamValueRange(String name) {
      // no parameter is a range
         Range range = null;
         return range;
         }

      /**
       * No value is ever valid.
       * @param   name   the name of the parameter.
       * @param   value   the value of the parameter.
       * @return    always {@code false}.
       */
      @Override
      public boolean isParameterValueValid(String name, Object value) {
         boolean is_valid = false;
         return is_valid;
         }

      }


//---------------------------
// Constructors
//---------------------------

   /**
    * Constructor.
    * @param   resources   the resource tags and their corresponding data.
    * @param   modes   the modes that this operator supports.
    * @param   source_names   the source names.
    * @param   source_classes   the source types required by this operation for
    *                           each of the above supported modes.
    * @param   parameter_list_descriptors   the parameter list descriptor for
    *                                       each mode.
    */
   protected CollectionDescriptor(String[][] resources, String[] modes, String[] source_names, Class<?>[][] source_classes, ParameterListDescriptor[] parameter_list_descriptors) {
      super(resources, modes, source_names, source_classes, parameter_list_descriptors);
      }


//---------------------------
// Overridden methods from javax.media.jai.OperationDescriptorImpl
//---------------------------

   /**
    * Collates and validates sources in both collection modes, non-collection
    * modes are handled by the super-class.
    * @param   mode   the rendering mode.
    * @param   pb   the parameter block.
    * @param   sb   sink for error messages.
    */
   @Override
   @SuppressWarnings("rawtypes")
   protected boolean validateSources(String mode, ParameterBlock pb, StringBuffer sb) {
   // The type of source is checked in the super-class method
   // (later that is). Here we collate sources into a single
   // collection
      boolean is_ok = true;

      DescriptorUtil.collateSources(pb);

      Collection sources = (Collection) pb.getSource(0);

      boolean is_rendered_mode = DescriptorUtil.isRenderedMode(mode);
      boolean is_collection_mode = DescriptorUtil.isCollectionMode(mode);

      boolean is_renderable_mode = DescriptorUtil.isRenderableMode(mode);
      boolean is_renderable_collection_mode = DescriptorUtil.isRenderableCollectionMode(mode);

      if (is_rendered_mode || is_collection_mode) {
         is_ok = DescriptorUtil.areAllSourceRendered(sources);
         if (false == is_ok) {
            String message = this.getNotAllRenderedErrorMessage();
            sb.append(message);
            }
         }
      else if (is_renderable_mode || is_renderable_collection_mode) {
         is_ok = DescriptorUtil.areAllSourceRenderable(sources);
         if (false == is_ok) {
            String message = this.getNotAllRenderableErrorMessage();
            sb.append(message);
            }
         }
      else {
         is_ok = false;
         String message = this.getNeitherCollectionNorRenderableCollectionModeErrorMessage(mode);
         sb.append(message);
         }

   // validations from the super-class
      is_ok = is_ok && super.validateSources(mode, pb, sb);

      return is_ok;
      }


//---------------------------
// External resources methods
//---------------------------

   /**
    * Gets the error message saying that this operator does not have any
    * enumerated parameters.
    * @return   the error message.
    */
   protected static String getNoEnumeratedParametersErrorMessage() {
      String key = Resources.NO_ENUMERATED_PARAMETERS;
      String message = Resources.getLocalizedString(key);
      return message;
      }

   /**
    * Gets the error message saying that parameter is unknown.
    * @param   name   the name of the offending parameter.
    * @return   the error message.
    */
   protected static String getUnknownParameterErrorMessage(String name) {
      String key = Resources.UNKNOWN_PARAMETER;
      String message = Resources.getLocalizedString(key, name);
      return message;
      }

   /**
    * Gets the error message saying that not all sources are rendered images.
    * @return   the error message.
    */
   protected String getNotAllRenderedErrorMessage() {
      String key = Resources.NOT_ALL_RENDERED_IMAGE;
      String message = Resources.getLocalizedString(key);
      return message;
      }

   /**
    * Gets the error message saying that not all sources are renderable images.
    * @return   the error message.
    */
   protected String getNotAllRenderableErrorMessage() {
      String key = Resources.NOT_ALL_RENDERABLE_IMAGE;
      String message = Resources.getLocalizedString(key);
      return message;
      }

   /**
    * Gets the error message saying that we are neither in collection nor
    * renderable collection mode.
    * @param   mode   the offending mode.
    * @return   the error message.
    */
   protected String getNeitherCollectionNorRenderableCollectionModeErrorMessage(String mode) {
      String key = Resources.NEITHER_COLLECTION_NOR_RENDERABLE_COLLECTION_MODE;
      String message = Resources.getLocalizedString(key, mode);
      return message;
      }

   }
